package com.trade.module.database.operation;

import com.google.common.base.Preconditions;
import com.trade.module.database.basic.ConstConfig;
import com.trade.module.database.meta.ColumnMetaData;
import com.trade.module.database.meta.PrimaryKeyMetaData;
import com.trade.module.database.meta.TableMetaData;
import org.apache.commons.lang.StringUtils;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @Desc: 数据元数据基本操作类
 * @Version: v1.0 2017/12/6 16:13
 * @Author: zfb
 * @JDK Version: 1.8.0_51
 */
public class DatabaseAnalyzer {

    /**
     * 获取列元数据集合
     * @param dbMeta     数据库元数据
     * @param dbName     数据库名称
     * @param tableName  表名称
     * @param dbType     数据库类型
     * @return List<ColumnMetaData>
     * @throws SQLException
     */
    public static List<ColumnMetaData> getColumns(DatabaseMetaData dbMeta, String dbName, String tableName, ConstConfig.DBType dbType) throws SQLException {
        return getColumns(dbMeta,dbName,tableName,dbType,null);
    }

    public static List<ColumnMetaData> getColumns(DatabaseMetaData dbMeta, String dbName, String tableName, ConstConfig.DBType dbType, String otherUser) throws SQLException {
        List<ColumnMetaData> columns = new LinkedList<ColumnMetaData>();
        if (dbType == ConstConfig.DBType.ORACLE) {
            dbName = StringUtils.isNotEmpty(otherUser) ? otherUser : dbMeta.getUserName();
        } else if (dbType != ConstConfig.DBType.DAMENG) {
            dbName = "%";
        }
        ResultSet columnResultSet = dbMeta.getColumns(null, dbName, tableName.toUpperCase(), "%");
        while (columnResultSet.next()) {
            String columnName = columnResultSet.getString("COLUMN_NAME");
            String columnType = columnResultSet.getString("TYPE_NAME");
            String remark = columnResultSet.getString("REMARKS");
            Integer length = columnResultSet.getInt("COLUMN_SIZE");
            Integer digitsLength = columnResultSet.getInt("DECIMAL_DIGITS");
            columns.add(new ColumnMetaData(columnName, columnType, remark, length, digitsLength));
        }
        return columns;
    }

    /**
     * 获取库中表的元数据集合
     * @param connection 连接
     * @param dbName 库名称
     * @return List<TableMetaData>
     * @throws SQLException
     */
    public static List<TableMetaData> getTablesSimple(Connection connection, String dbName) throws SQLException {
        return getTablesSimple(connection,dbName,null);
    }

    /**
     * 获取库中表的元数据集合
     * @param connection 连接
     * @param dbName 库名称
     * @param otherUser 其他实例名称
     * @return List<TableMetaData>
     * @throws SQLException
     */
    public static List<TableMetaData> getTablesSimple(Connection connection, String dbName, String otherUser) throws SQLException {
        Preconditions.checkArgument(!connection.isClosed(), "connection is closed");
        DatabaseMetaData dbMeta = connection.getMetaData();
        List<TableMetaData> tables = new LinkedList<TableMetaData>();

        String driverName = connection.getMetaData().getDriverName();
        //需要判断数据库类型，组装不同的查询条件
        if (StringUtils.startsWithIgnoreCase(driverName, "Oracle")) {
            dbName = StringUtils.isNotEmpty(otherUser) ? otherUser : dbMeta.getUserName();
        } else if (StringUtils.startsWithIgnoreCase(driverName, "Microsoft")) {
            dbName = null;
        }

        ResultSet tablesResultSet = dbMeta.getTables(connection.getCatalog(), dbName, null, new String[]{"TABLE"});
        while (tablesResultSet.next()) {
            String tableName = tablesResultSet.getString("TABLE_NAME");
            String remark = tablesResultSet.getString("REMARKS");
            tables.add(new TableMetaData(tableName, remark));
        }
        return tables;
    }

    /**
     * 获取主键元数据集合
     * @param dbMeta     数据库元数据
     * @param dbName     数据库名称
     * @param tableName  表名称
     * @return List<PrimaryKeyMetaData>
     * @throws SQLException
     */
    public static List<PrimaryKeyMetaData> getPrimaryKeys(DatabaseMetaData dbMeta, String dbName, String tableName) throws SQLException {
        List<PrimaryKeyMetaData> pkList = new ArrayList<>();
        ResultSet primaryKeySet = dbMeta.getPrimaryKeys(null, null, tableName);
        while (primaryKeySet.next()) {
            String columnName = primaryKeySet.getString("COLUMN_NAME");
            //Oracle结果中无字段TYPE_NAME
            pkList.add(new PrimaryKeyMetaData(columnName, "TYPE_NAME"));
        }
        return pkList;
    }
}
